import { ITERATE_KEY, TrackOpTypes, TriggerOpTypes } from '../utils/index.js';
import { activeEffect, targetMap } from './effect.js';

// 触发类型对应的依赖类型映射表 每个触发类型对应哪些依赖类型
const triggerTypeMap = {
  [TriggerOpTypes.SET]: [TrackOpTypes.GET],
  [TriggerOpTypes.ADD]: [TrackOpTypes.HAS, TrackOpTypes.GET, TrackOpTypes.ITERATE],
  [TriggerOpTypes.DELETE]: [TrackOpTypes.HAS, TrackOpTypes.GET, TrackOpTypes.ITERATE],
};

/**
 * 触发属性变化的函数
 * @param {*} target 目标对象
 * @param {TriggerOpTypes} type 触发类型
 * @param {*} key 属性名
 */
export default function trigger(target, type, key) {
  const effectFns = getEffectFns(target, type, key);
  if (!effectFns) return;
  for (const effectFn of effectFns) {
    // 跳过当前正在执行的副作用函数, 避免无限循环
    if (effectFn === activeEffect) continue;
    const { scheduler } = effectFn.options; // 获取副作用函数的调度函数
    // 让开发者自己处理副作用函数的执行
    if (scheduler) {
      scheduler(effectFn); // 如果有调度函数，就调用调度函数，将副作用函数作为参数传递
    } else {
      effectFn();
    }
  }
}

/**
 * 获取触发属性变化的依赖函数集合
 * @param {*} target 目标对象
 * @param {TriggerOpTypes} type 触发类型
 * @param {*} key 属性名
 * @returns 依赖函数集合
 */
const getEffectFns = (target, type, key) => {
  // 获取依赖函数
  const propMap = targetMap.get(target);
  if (!propMap) return;

  // 新增与删除有额外的迭代操作
  const keys = [key];
  if (type === TriggerOpTypes.ADD || type === TriggerOpTypes.DELETE) {
    keys.push(ITERATE_KEY);
  }

  const effectFns = new Set();

  for (const key of keys) {
    const typeMap = propMap.get(key); // 根据属性名，获取属性的依赖关系map
    if (!typeMap) continue;
    // 根据触发类型，获取对应的依赖类型
    const trackTypes = triggerTypeMap[type];
    for (const trackType of trackTypes) {
      // 根据依赖类型，获取对应的依赖函数集合
      const dep = typeMap.get(trackType);
      if (!dep) continue;
      // 遍历依赖函数集合，将每个依赖函数添加到 effectFns 集合中
      dep.forEach((effectFn) => effectFns.add(effectFn));
    }
  }
  return effectFns;
};
